#include <iostream>
#include <signal.h>

#include "TcpServer.h"
#include "EventLoop.h"
#include "TcpConnection.h"
#include "Buffer.h"

using namespace std::placeholders;

class IgnoreSigPipe {
public:
    IgnoreSigPipe() {
        ::signal(SIGPIPE, SIG_IGN);
    }
};

IgnoreSigPipe serverInit;

void defaultConnectionCallback(TcpConnectionPtr conn) {
    if (conn->isConnected()) {
        std::cout << "TcpConnection connect" << std::endl;
    } else {
        std::cout << "TcpConnection disconnect" << std::endl;
    }
}

void defaultMessageCallback(TcpConnectionPtr conn, Buffer& buffer) {
    buffer.printContent();
}

TcpServer::TcpServer(EventLoop* loop, InetAddress& serverAddr) :
    loop_(loop),
    serverAddr_(serverAddr),
    acceptor_(new Acceptor(loop, serverAddr)),
    threadPool_(loop),
    connectionCallback_(std::bind(defaultConnectionCallback, _1)),
    messageCallback_(std::bind(defaultMessageCallback, _1, _2))
{
    acceptor_->setNewConnectCallback(std::bind(&TcpServer::newConnectionCallback, this, _1, _2));
}

TcpServer::~TcpServer() {

}

void TcpServer::start() {
    threadPool_.start();
    acceptor_->listen();
}

void TcpServer::newConnectionCallback(int connfd, InetAddress& peerAddr) {
    std::cout << "TcpSer::newConnectCallback" << std::endl;
    EventLoop* ioloop = threadPool_.getNextLoop();
    TcpConnectionPtr conn = std::make_shared<TcpConnection>(ioloop, connfd, serverAddr_, peerAddr);
    connections_.insert(conn);
    conn->setConnectionCallback(connectionCallback_);
    conn->setMessageCallback(messageCallback_);
    conn->setWriteCompleteCallback(writeCompleteCallback_);
    conn->setCloseCallback(std::bind(&TcpServer::removeConnection, this, _1));
    ioloop->runInLoop(std::bind(&TcpConnection::connectEstablished, conn));

    std::cout << "current connections size : " << connections_.size() << std::endl;
}

void TcpServer::removeConnection(TcpConnectionPtr conn) {
    connections_.erase(conn);
    loop_->queueInLoop(std::bind(&TcpConnection::connectDestroyed, conn));
}